import CircularLink from "./component/CircularLink";
import Node from "./component/Node";
import StepCompute from "./component/StepCompute";

export class LotteryGame{
    private _circularLink:CircularLink;
    private _stepCompute:StepCompute;
    private _curFocusTarget:Node|null;
    private focusCallBack:(a:any,b:any)=>void;
    private endCallBack:(b:any)=>void;
    private intervalTarget:any;
    private target:any;
    //1 开始 2 寻找目标节点 3结束 0初始化
    private status = 0;
    /**
     * 
     * @param {any[]} arr 抽奖数据数组 
     * @param {(oldValue,newValue)=>void} focusCallBack 聚焦回调 
     * @param {(target)=>void} endCallBack 结束回调 
     */
    constructor(arr:any[],focusCallBack:(oldValue:any,newValue:any)=>void,endCallBack:(b:any)=>void){
        this._circularLink = new CircularLink();
        this._stepCompute = new StepCompute();
        this._curFocusTarget = null;
        this.target = null;
        this.focusCallBack = focusCallBack
        this.endCallBack = endCallBack;
        this.intervalTarget = null;
        this.init(arr)
    }
    /**
     * 
     * @param {StepComputeData} cfg 抽奖配置
     */
    public setStepConfig(cfg:IStepComputeData){
        this._stepCompute = new StepCompute(cfg);
    }
    /**
     * @param {target} num 获得焦点 
     */
    public focus(num:any){
        let oldTarget = this._curFocusTarget;
        let target = this._circularLink.find(num);
        this._curFocusTarget = target;
        this.focusCallBack && this.focusCallBack(oldTarget?.value,target?.value);
    }
    public init(arr:any[]){
        if(!arr){
            console.log("抽奖数组未初始化")
            return;
        }
        arr.forEach((item)=>{
            this._circularLink.insert(item);
        })
        this._curFocusTarget = this._circularLink.head;
    }
    /**
     * 开始抽奖
     * @param {any} target 中奖目标
     * @param {number} findTargetTime 寻找中奖目标的时间
     */
    public start(target:any,findTargetTime:number){
        if(this._circularLink.length == 0){
            throw "未初始化抽奖数组 请调用init方法初始化数组"
        }
        this.status = 1;
        if(this._curFocusTarget == null){
            this._curFocusTarget = this._circularLink.head;
        }
        this._stepCompute.reset();
        this.target = target;
        findTargetTime = ((1-Math.random()*0.2) * findTargetTime)
        if(findTargetTime < 100){
            this.end();
        } else {
            setTimeout(() => {
                this.findTargetStatus();
            }, findTargetTime);
        }
        clearInterval(this.intervalTarget)
        this.intervalTarget = setInterval(() => {
            this.update();
        }, 16);
    }
    /**游戏结束 */
    private gameOver(){
        this.status = 3;
        this.endCallBack && this.endCallBack(this.target);
    }
    /**直接结束 */
    private end(){
        let oldTarget = this._curFocusTarget;
        let target = this._circularLink.find(this.target);
        this._curFocusTarget = target;
        this.focusCallBack && this.focusCallBack(oldTarget?.value,target?.value);
        this.gameOver();
    }
    private findTargetStatus(){
        this.status = 2;
    }
    /**是运行状态 */
    public isActive(){
        return !(this.status == 0 || this.status == 3);
    }
    public update(){
        if(!this.isActive()){
            return;
        }
        this._stepCompute.update();
        let step = this._stepCompute.step;
        if(step != 0){
            let oldTarget = this._curFocusTarget;
            let target = this._curFocusTarget = this.stepUp(step);
            this.focusCallBack && this.focusCallBack(oldTarget?.value,target?.value);
            if(this.status == 2){
                if(target?.value == this.target){
                    this.gameOver();
                }
            }
        }
    }
    private stepUp(n:number){
        let nextTarget = this._curFocusTarget as Node;
        for(let i = 0;i<n;i++){
            nextTarget = nextTarget.next as Node;
        }
        return nextTarget;
    }
}
